﻿
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Xml;
using System.Xml.XPath;


// http://stackoverflow.com/questions/3151450/google-geolocation-api-use-longitude-and-latitude-to-get-address

namespace ReverseGeoLookup
{
    class ReverseGeoLookup
    {

        // 	-40.402864	-20.342288	0.0	0.0	BR-262 - Pistal Lateral - Vila Capixaba, Cariacica - ES, Brazil
        // -40.288124	-20.355536	0.0	0.0	R. Natal, 1-61 - Praia de Itapoã, Vila Velha - ES, 29101-710, Brazil
        // http://code.google.com/apis/maps/documentation/geocoding/#ReverseGeocoding
        //http://maps.google.com/maps/api/geocode/xml?latlng=40.714224,-73.961452&sensor=false
        public static string ReverseGeoLoc(string longitude, string latitude,
            out string Address_ShortName,
            out string Address_country,
            out string Address_administrative_area_level_1,
            out string Address_administrative_area_level_2,
            out string Address_administrative_area_level_3,
            out string Address_colloquial_area,
            out string Address_locality,
            out string Address_sublocality,
            out string Address_neighborhood)
        {

            Address_ShortName = "";
            Address_country = "";
            Address_administrative_area_level_1 = "";
            Address_administrative_area_level_2 = "";
            Address_administrative_area_level_3 = "";
            Address_colloquial_area = "";
            Address_locality = "";
            Address_sublocality = "";
            Address_neighborhood = "";

            XmlDocument doc = new XmlDocument();

            try
            {
                doc.Load("http://maps.googleapis.com/maps/api/geocode/xml?latlng=" + latitude + "," + longitude + "&sensor=false");
                XmlNode element = doc.SelectSingleNode("//GeocodeResponse/status");
                if (element.InnerText == "ZERO_RESULTS")
                {
                    return ("No data available for the specified location");
                }
                else
                {

                    element = doc.SelectSingleNode("//GeocodeResponse/result/formatted_address");

                    string longname = "";
                    string shortname = "";
                    string typename = "";
                    bool fHit = false;


                    XmlNodeList xnList = doc.SelectNodes("//GeocodeResponse/result/address_component");
                    foreach (XmlNode xn in xnList)
                    {
                        try
                        {
                            longname = xn["long_name"].InnerText;
                            shortname = xn["short_name"].InnerText;
                            typename = xn["type"].InnerText;


                            fHit = true;
                            switch (typename)
                            {
                                //Add whatever you are looking for below
                                case "country":
                                    {
                                        Address_country = longname;
                                        Address_ShortName = shortname;
                                        break;
                                    }

                                case "locality":
                                    {
                                        Address_locality = longname;
                                        //Address_locality = shortname; //Om Longname visar sig innehålla konstigheter kan man använda shortname istället
                                        break;
                                    }

                                case "sublocality":
                                    {
                                        Address_sublocality = longname;
                                        break;
                                    }

                                case "neighborhood":
                                    {
                                        Address_neighborhood = longname;
                                        break;
                                    }

                                case "colloquial_area":
                                    {
                                        Address_colloquial_area = longname;
                                        break;
                                    }

                                case "administrative_area_level_1":
                                    {
                                        Address_administrative_area_level_1 = longname;
                                        break;
                                    }

                                case "administrative_area_level_2":
                                    {
                                        Address_administrative_area_level_2 = longname;
                                        break;
                                    }

                                case "administrative_area_level_3":
                                    {
                                        Address_administrative_area_level_3 = longname;
                                        break;
                                    }

                                default:
                                    fHit = false;
                                    break;
                            }


                            if (fHit)
                            {
                                Console.Write(typename);
                                Console.ForegroundColor = ConsoleColor.Green;
                                Console.Write("\tL: " + longname + "\tS:" + shortname + "\r\n");
                                Console.ForegroundColor = ConsoleColor.Gray;
                            }
                        }

                        catch (Exception e)
                        {
                            //Node missing either, longname, shortname or typename
                            fHit = false;
                            Console.Write(" Invalid data: ");
                            Console.ForegroundColor = ConsoleColor.Red;
                            Console.Write("\tX: " + xn.InnerXml + "\r\n");
                            Console.ForegroundColor = ConsoleColor.Gray;
                        }


                    }

                    //Console.ReadKey();
                    return (element.InnerText);
                }

            }
            catch (Exception ex)
            {
                return ("(Address lookup failed: ) " + ex.Message);
            }
        }
    }

}


//<GeocodeResponse> 
// <status>OK</status> 
// <result> 
//  <type>street_address</type> 
//  <formatted_address>277 Bedford Ave, Brooklyn, NY 11211, USA</formatted_address> 
//  <address_component> 
//   <long_name>277</long_name> 
//   <short_name>277</short_name> 
//   <type>street_number</type> 
//  </address_component> 
//  <address_component> 
//   <long_name>Bedford Ave</long_name> 
//   <short_name>Bedford Ave</short_name> 
//   <type>route</type> 
//  </address_component> 
//  <address_component> 
//   <long_name>Brooklyn</long_name> 
//   <short_name>Brooklyn</short_name> 
//   <type>sublocality</type> 
//   <type>political</type> 
//  </address_component> 
//  <address_component> 
//   <long_name>New York</long_name> 
//   <short_name>New York</short_name> 
//   <type>locality</type> 
//   <type>political</type> 
//  </address_component> 
//  <address_component> 
//   <long_name>Kings</long_name> 
//   <short_name>Kings</short_name> 
//   <type>administrative_area_level_2</type> 
//   <type>political</type> 
//  </address_component> 
//  <address_component> 
//   <long_name>New York</long_name> 
//   <short_name>NY</short_name> 
//   <type>administrative_area_level_1</type> 
//   <type>political</type> 
//  </address_component> 
//  <address_component> 
//   <long_name>United States</long_name> 
//   <short_name>US</short_name> 
//   <type>country</type> 
//   <type>political</type> 
//  </address_component> 
//  <address_component> 
//   <long_name>11211</long_name> 
//   <short_name>11211</short_name> 
//   <type>postal_code</type> 
//  </address_component> 
//  <geometry> 
//   <location> 
//    <lat>40.7142330</lat> 
//    <lng>-73.9612910</lng> 
//   </location> 
//   <location_type>ROOFTOP</location_type> 
//   <viewport> 
//    <southwest> 
//     <lat>40.7110854</lat> 
//     <lng>-73.9644386</lng> 
//    </southwest> 
//    <northeast> 
//     <lat>40.7173806</lat> 
//     <lng>-73.9581434</lng> 
//    </northeast> 
//   </viewport> 
//  </geometry> 
// </result> 
//</GeocodeResponse> 